{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Design - The Qmod Language"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The first step in quantum software development is designing your software, your algorithm. Classiq features a unique high-level modeling language called Qmod, that naturally captures the core concepts of quantum algorithm design. There are two ways to design in Qmod:\n",
    "* Directly, via the Classiq IDE using the Qmod native syntax\n",
    "* With Classiq Python SDK package, that gives access to the Qmod language via Python\n",
    "\n",
    "Once you finished designing your algorithm you send it to the Classiq synthesis engine (compiler) to create a concrete quantum circuit implementation - a quantum program."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Concrete Example "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's get started and understand Qmod through a concrete example. \n",
    "\n",
    "Our task is to design a quantum algorithm that computes the arithemtic operation $y=x^2+1$ coherently, for a quantum variable $|x\\rangle$ that is a superpostion of all the numbers between $0$ and $7$:\n",
    "$\\begin{equation}\n",
    "|x\\rangle = \\frac{1}{\\sqrt{8}}(|0\\rangle+|1\\rangle+\\dots +|7\\rangle.\n",
    "\\end{equation}$\n",
    "The expected output is \n",
    "\n",
    "$\\begin{equation}\n",
    "|x\\rangle |y\\rangle = |x\\rangle |x^2+1\\rangle = \\frac{1}{\\sqrt{8}}\\sum_{i=0}^{7}|i\\rangle|i^2+1\\rangle,\n",
    "\\end{equation}$\n",
    "where $|x\\rangle$ is entangled to $|y\\rangle$.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sounds complicated? The following code in Qmod with a few lines creates the desired algorithm with Classiq:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:28:21.042152Z",
     "iopub.status.busy": "2024-05-07T13:28:21.041703Z",
     "iopub.status.idle": "2024-05-07T13:28:23.680899Z",
     "shell.execute_reply": "2024-05-07T13:28:23.680103Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import Output, QNum, allocate, hadamard_transform, qfunc\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def main(x: Output[QNum], y: Output[QNum]):\n",
    "\n",
    "    allocate(4, x)\n",
    "    hadamard_transform(x)  # creates a uniform superposition\n",
    "    y |= x**2 + 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "and the desired quantum program can be synthesized and viewed:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:28:23.686679Z",
     "iopub.status.busy": "2024-05-07T13:28:23.685168Z",
     "iopub.status.idle": "2024-05-07T13:28:26.256502Z",
     "shell.execute_reply": "2024-05-07T13:28:26.255810Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Opening: https://platform.classiq.io/circuit/83bade43-cef0-4286-83cc-ac1aafede94d?version=0.41.0.dev39%2B79c8fd0855\n"
     ]
    }
   ],
   "source": [
    "from classiq import create_model, show, synthesize\n",
    "\n",
    "quantum_program = synthesize(create_model(main))\n",
    "show(quantum_program)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div  style=\"text-align:center;\">\n",
    "    <img src=\"https://docs.classiq.io/resources/design.gif\">\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Key Qmod Principles"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The above code is a quantum model written in Qmod. A model is composed of quantum functions with at least one quantum function called `main`. In Python, quantum functions are defined using regular Python functions decorated with `@qfunc`, and in the native Qmod syntax they are defined with the `qfunc` keyword.  \n",
    "\n",
    "Quantum functions manipulate quantum objects which are represented using quantum variables. Every variable needs to be declared and initialized before it is used. \n",
    "\n",
    "The following explains these principles:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<u>**1) There must be a `qfunc` decorator in Python or keyword in the native syntax**</u>\n",
    "\n",
    "We can see the `qfunc` decorator (`@qfunc`) in the Python implementation, and the corresponding keyword in the native implementation. This  in Qmod that we are dealing with quantum functions that manipulate quantum objects. \n",
    "\n",
    "<u>**2) There must be a `main` function**</u>\n",
    "\n",
    "Every quantum algorithm written in Qmod must have a `main` function. From this `main` function the quantum program is created using the `synthesize(create_model(main))` command in Python, or just by pressing the Synthesis button in the IDE.\n",
    "\n",
    "<u>**3) The arguments of the `main` function must be declared as `output`s**</u>\n",
    "\n",
    "In the above example, there are two arguments of the `main` function: `x` and `y`, both are quantum variables. The type of both them is `QNum`(`qnum` in the native syntax) which stands for a quantum number (see [Quantum Variables](./quantum_variables.ipynb)). In addition to the type, the variables of the `main` function must be declared as `output` which indicates these quantum variables are not initialized outside the scope of the function.\n",
    "<details> \n",
    "<summary> Types of Quantum Variables </summary>\n",
    "In Qmod there are 3 types of quantum variables:\n",
    "\n",
    "1. `QBit` (`qbit`)\n",
    "2. `QArray[QBit]` (`qbit[]`)\n",
    "3. `QNum` (`qnum`)\n",
    "</details>\n",
    "\n",
    "\n",
    "<u>**4) Every quantum variable needs to be declared before it is used**</u>\n",
    "\n",
    "Here we declare the the variables `x` and `y` as arguments of the `main` function, but we could also declare variables in the scope of a function (see [Quantum Variables](./quantum_variables.ipynb)).\n",
    "<details> \n",
    "<summary> Declaration within a Scope of a Function </summary>\n",
    "You can declare a quantum variable within the scope of a function with \n",
    "\n",
    "=== Python\n",
    "        x = QNum('x')\n",
    "\n",
    "=== Native\n",
    "        x:qnum;\n",
    "\n",
    "</details>\n",
    "\n",
    "<u>**5) Every quantum variable needs to be initialized**</u>\n",
    "\n",
    "After a quantum variable is declared it needs to be initialized. There are several ways to initialize quantum variables, and in the above example we can see two ways:\n",
    "\n",
    "* `x` is initialized with the `allocate` operation.\n",
    "* `y` i initialized with the `|=` (`=` in native) numeric assignment.\n",
    "\n",
    "<details> \n",
    "<summary> Types of Initializations </summary>\n",
    "There are a few ways to initialize a quantum variable:\n",
    "\n",
    "1. With `allocate` or `allocate_num` \n",
    "2. With `prepare_int`, `prepare_state` or `prepare_amplitudes`\n",
    "3. As the result of a numeric operation, like in the example above\n",
    "4. With the `bind` operation (`->` in native)\n",
    "5. With any function that declares its quantum variable argument as `output`\n",
    "\n",
    "</details>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Next Steps\n",
    "Now that you are familiar with the foundations of Qmod, you can continue to understand it in a bit more detail, with:\n",
    "* Quantum Variables and Functions\n",
    "* Quantum Operations\n",
    "* Classical Control Flow"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:28:26.321902Z",
     "iopub.status.busy": "2024-05-07T13:28:26.321314Z",
     "iopub.status.idle": "2024-05-07T13:28:26.337269Z",
     "shell.execute_reply": "2024-05-07T13:28:26.336415Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import write_qmod\n",
    "\n",
    "write_qmod(create_model(main), \"design\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.11.7 ('classiq_devolpment')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  },
  "vscode": {
   "interpreter": {
    "hash": "e992e515f6583afc67b46eeabcda0f30363069fab8b382c7517b274ba7a59477"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
